home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir24
/
jnos110g.zip
/
CURSES.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-17
|
11KB
|
524 lines
#ifdef linux
#include <ncurses.h>
#else
#include <curses.h>
#endif
#include <term.h>
#undef FALSE
#undef TRUE
#define SCREEN_INTERNAL
#include "hardware.h"
#include "proc.h"
#include "socket.h"
#undef tputs
#include "tty.h"
extern int Numrows, Numcols;
static WINDOW *curwin, *curss;
static int in_ss;
struct keytrie
{
enum {KT_DEF, KT_TRIE, KT_VAL} kt_type;
union
{
struct keytrie *ktu_trie;
#define kt_trie kt_u.ktu_trie
int ktu_val;
#define kt_val kt_u.ktu_val
} kt_u;
};
static struct keytrie *keys;
static void
key_init()
{
int i;
keys = mallocw(256 * sizeof *keys);
for (i = 256; i--; )
{
keys[i].kt_type = KT_DEF;
keys[i].kt_val = i;
}
}
static void
key_add(str, val)
const char *str;
int val;
{
const char *old;
struct keytrie *t;
int c, i;
/*
* Follow the trie until we get to the right subtrie for the string, then
* add the value. If we hit a KT_DEF, expand the trie. If we hit a KT_VAL
* we have a conflict; drop the key on the floor. (We can't use timeouts.)
* (Well, actually, we could, but I'll be darned if *I* want to write it!)
*/
if (!str || !*str)
return; /* no key to define */
old = str;
t = keys;
while (str[1])
{
c = uchar(*str++);
if (t[c].kt_type == KT_DEF)
{
t[c].kt_type = KT_TRIE;
t[c].kt_trie = mallocw(256 * sizeof (struct keytrie));
for (i = 256; i--; )
{
t[c].kt_trie[i].kt_type = KT_DEF;
t[c].kt_trie[i].kt_val = i;
}
}
else if (t[c].kt_type != KT_TRIE)
return;
t = t[c].kt_trie;
}
c = uchar(*str);
if (t[c].kt_type == KT_TRIE)
return;
t[c].kt_type = KT_VAL;
t[c].kt_val = val;
}
void
ioinit()
{
initscr();
nonl();
raw();
noecho();
Numrows = LINES;
Numcols = COLS;
init_sys();
/* build a trie of function keys */
key_init();
key_add(key_down, DNARROW);
key_add(key_f0, -3);
key_add(key_f1, -4);
key_add(key_f2, -5);
key_add(key_f3, -6);
key_add(key_f4, -7);
key_add(key_f5, -8);
key_add(key_f6, -9);
key_add(key_f7, -10);
key_add(key_f8, -11);
key_add(key_f9, -2); /* F10 traditionally is NOS escape */
key_add(key_left, LTARROW);
key_add(key_right, RTARROW);
key_add(key_up, UPARROW);
key_add("\177", '\b'); /* so DEL behaves as BS */
}
void
iostop()
{
deinit_sys();
endwin();
}
void
swapscreen(old, new)
struct session *old, *new;
{
if (old == new)
return;
if (old != NULLSESSION && old->screen != NULLSCREEN)
old->screen->in_ss = in_ss;
if (new != NULLSESSION && new->screen != NULLSCREEN)
{
curwin = new->screen->win;
clearok(curwin, TRUE);
touchwin(curwin);
wnoutrefresh(curwin);
if (!new->split || !new->screen->sswin)
curss = 0;
else
{
curss = new->screen->sswin;
touchwin(curss);
wnoutrefresh(curss);
}
in_ss = new->screen->in_ss;
}
}
static int
in_split(s)
struct session *s;
{
return s->screen->in_ss;
}
void
putch(c)
int c;
{
WINDOW *w;
int x, y;
if (in_ss && curss)
w = curss;
else
w = curwin;
if (c == 7)
write(1, "\7", 1);
else if (c == '\r' || c == '\t' || c == '\b')
waddch(w, c);
else if (c == '\n')
{
/* waddch() does clrtoeol() implicitly. This breaks us. */
getyx(w, y, x);
if (++y > w->_regbottom)
{
y--;
scroll(w);
}
wmove(w, y, 0);
}
else if (c < 32)
return;
else if (c > 126)
return;
else
waddch(w, c);
}
void
sputch(s, c)
struct session *s;
int c;
{
WINDOW *w;
int x, y;
if (in_split(s) && s->screen->sswin)
w = s->screen->sswin;
else
w = s->screen->win;
if (c == 7)
write(1, "\7", 1);
else if (c == '\r' || c == '\t' || c == '\b')
waddch(w, c);
else if (c == '\n')
{
/* waddch() does clrtoeol() implicitly. This breaks us. */
getyx(w, y, x);
if (++y > w->_regbottom)
{
y--;
scroll(w);
}
wmove(w, y, 0);
}
else if (c < 32)
return;
else if (c > 126)
return;
else
waddch(w, c);
}
void
cputs(s)
char *s;
{
if (in_ss && curss)
waddstr(curss, s);
else
waddstr(curwin, s);
}
void
scputs(ses, s)
struct session *ses;
char *s;
{
if (in_split(ses) && ses->screen->sswin)
waddstr(ses->screen->sswin, s);
else
waddstr(ses->screen->win, s);
}
void
clreol()
{
if (in_ss && curss)
wclrtoeol(curss);
else
wclrtoeol(curwin);
}
void
sclreol(s)
struct session *s;
{
if (in_split(s) && s->screen->sswin)
wclrtoeol(s->screen->sswin);
else
wclrtoeol(s->screen->win);
}
/*
* The display process. Under *ix, all output goes to curses windows; since
* I/O is buffered until a wrefresh(), we don't need to limit ourselves to the
* current window and block other windows' I/O. (A window sleeping on a More?
* is the exception; but it's blocking on the keyboard, not the display.)
* This does mean that you might lose information if you don't have "more"
* enabled on a window; I don't think this matters much.
*
* Note that the real work is done by rflush(). The Display process no longer
* exists.
*/
void
rflush()
{
struct session *sp;
int i, c, cnt;
for (sp = Sessions, i = 0; i < Nsessions; sp++, i++)
{
if (sp->type == FREE)
continue;
if (!sp->screen || !sp->screen->win) /* "shouldn't happen" */
continue;
if (sp->morewait == 1) /* More prompt, no key yet */
continue;
if (sp->morewait == 2)
{
sp->morewait = 0;
sputch(sp, '\r');
sclreol(sp);
}
cnt = 0;
while (socklen(sp->output, 0) > 0)
{
if ((c = rrecvchar(sp->output)) == -1)
continue;
cnt++;
if (!sp->split || c != 0x0a)
sputch(sp, c);
else
{
scputs(sp, Eol);
sclreol(sp);
}
if (sp->record != NULLFILE)
{
if (c == '\r' || c == '\n')
fflush(sp->record);
if (c != '\r' || sockmode(sp->output, -1) != SOCK_ASCII)
putc(c, sp->record);
}
if (sp->flowmode && c == '\n' && --sp->row <= 0)
{
scputs(sp, "--More--");
sp->morewait = 1;
break;
}
}
}
if (curwin)
wnoutrefresh(curwin);
if (curss)
wnoutrefresh(curss);
doupdate();
}
void
j_newscreen(sp)
struct session *sp;
{
if (sp == NULLSESSION)
return;
sp->screen = mallocw(sizeof *sp->screen);
curwin = sp->screen->win = newwin(LINES - (sp->split? 2: 0), COLS, 0, 0);
scrollok(curwin, TRUE);
in_ss = 0;
sp->screen->in_ss = 0;
if (sp->split)
{
sp->screen->sswin = newwin(2, COLS, LINES - 2, 0);
curss = sp->screen->sswin;
scrollok(curss, TRUE);
}
else
{
sp->screen->sswin = 0;
curss = 0;
}
}
void
freescreen(sp)
struct session *sp;
{
if (sp == NULLSESSION || sp->screen == NULLSCREEN)
return;
delwin(sp->screen->win);
if (sp->screen->sswin)
delwin(sp->screen->sswin);
j_free(sp->screen);
}
/* Now we come to the emulation of the PC console as seen by Turbo C (bleah) */
void
clrscr()
{
wclear(curwin);
if (curss)
werase(curss);
}
int
wherex()
{
int x, y;
if (in_ss && curss)
getyx(curss, y, x);
else
getyx(curwin, y, x);
return x + 1;
}
int
wherey()
{
int x, y;
if (in_ss && curss)
{
getyx(curss, y, x);
y += LINES - 2;
}
else
getyx(curwin, y, x);
return y + 1;
}
void
window(x, y, w, h)
int x, y, w, h;
{
in_ss = (y == LINES - 1);
}
void
gotoxy(x, y)
int x, y;
{
if (in_ss && curss)
wmove(curss, y - LINES + 1, x - 1);
else
wmove(curwin, y - 1, x - 1);
}
void
highvideo()
{
if (in_ss && curss)
wstandout(curss);
else
wstandout(curwin);
}
void
normvideo()
{
if (in_ss && curss)
wstandend(curss);
else
wstandend(curwin);
}
void
_setcursortype(t)
int t;
{
curs_set(t);
}
/*
* Read from the keyboard, "blocking" via the NOS scheduler.
* We handle function keys ourselves: curses wants to use alarms to do it,
* which is somewhat dangerous in this case because it leaves us waiting on
* a tick from a nonexistent timer (curses doesn't bother checking to see if
* someone's got an alarm pending).
*/
static int
kbchar()
{
extern int Keyboard;
unsigned char ch;
int i;
do
{
pwait(&Keyboard);
}
while ((i = read(0, &ch, 1)) == 0 || (i == -1 && errno == EWOULDBLOCK));
if (i < 0)
{
tprintf("NOS PANIC: Lost keyboard\n");
where_outta_here(1);
}
return ch;
}
int
kbread()
{
static int ungets[10];
struct keytrie *t;
static int unget;
int ungetc[10];
int c, i, u;
i = 0;
u = 0;
if (unget > i)
c = ungets[i++];
else
c = kbchar();
ungetc[u++] = c;
t = keys;
while (t[c].kt_type == KT_TRIE)
{
t = t[c].kt_trie;
if (unget > i)
c = ungets[i++];
else
c = kbchar();
ungetc[u++] = c;
}
if (t[c].kt_type == KT_VAL)
{
u = 0;
c = t[c].kt_val;
}
while (i < unget)
ungetc[u++] = ungets[i++];
if (u)
{
c = ungetc[0];
for (i = u; i; i--)
ungets[i - 1] = ungetc[i];
unget = u - 1;
}
return c;
}